TypeORM 规则
实体目录
每一个实体目录对应数据库下的一张实体表
- 在实体目录下建立对应 实体类 .entity.ts 文件,定义表字段和表关联关系
- 在实体目录下建立对应 控制器 .controller.ts 文件,定义路由,基础增删改查路由和一多关联路由
- 在实体目录下建立对应 逻辑层 .service.ts 文件,定义与数据库交互逻辑,sql 操作在此
- 在实体目录下建立对应 模块层 .module.ts 文件,定义模块,汇集 entity、controller、service 三者,最终在 app.module.ts 中注册生效
实战总结
- 每个实体文件都有基础的增删改查方法,外加关联操作的增删改查方法
- 关联操作全部放在非用户实体目录下(放在哪一方都可以,推荐非用户方),防止用户目录逻辑复杂
- 关联操作要放在最上方,防止动态路由覆盖无效
注意事项
- 查询单条,必须用 param 动态路由参数,或者 param 与 query 参数组合因为 restful API 请求中查询的 path 是相同的,通过param 参数来区分查询单条还是多条
- 关联查询创建 POST 接口,在使用 APIpost 工具创建数据的时候无法插入 外键字段 ,解决方式:在实体中必须显式的定义外键字段
- 关联查询是双向的,即:关联查询接口定义的位置,既可以在 user的 service 中,也可以在自身的 service 中实现(建议在 自身 目录下实现)
- 关联操作,使用到用户id user_id 的参数的地方,现在是通过http参数,实际开发中要通过解析 token 获取 user_id
- 在 .service.ts 中进行多对多关联操作时,如果使用其他实体关系,要在 .module.ts 中注册其他实体的实体类
- 使用动态路由的时候注意:如果 path 相同,动态路由在上的时候会覆盖拦截下方的路由,因此 path 长的路由要放在最上面 /api/v1/roles/byUser 在上 /api/v1/roles/3 在下,否则 /api/v1/roles/byUser 会被覆盖无效
- 在 app.nodule.ts 中完成 mysql 数据库配置 注意 synchronize: true 配置项为 true 代表每次保存程序后 NEST 会根据实体类关系,动态创建修改数据库表结构,因此在开发环境此参数需要设置为 false,防止更改线上的数据库结构,这样在开发环境设置 synchronize: true 后,保存时会自动创建数据库中表结构
- 多对多关系中,建立的中间表是没有主键列的,只有两个 id 列
- Repository 中的 save 方法(没有主键则插入,有主键则修改)场景一:可作为 插入 方法使用,没有自动插入场景二:可作为 修改 方法使用,但是修改是可以修改实体的部分字段的,所以必须 Repository.find 查询出完整实体,然后使用 Repository.merge 合并后再 save 场景三:不存在主键插入,存在主键更新,使用方式与 场景二 相同场景四:由于 save 方法可以传入实体列表,所以可以用于 批量插入&修改
- Repository 中的 save 方法修改是针对于实体的,update 方法则是针对实体中的部分字段的
总结
- 简单 sql 操作优先使用 Repository API 实现,推荐:当前 实体类 下当前表的增删改、查单条、查所有 这些逻辑用 Repository API
- 复杂 sql 考虑使用 QueryBuilder 实现
- 及其复杂的操作或者性能有关的关键操作,考虑使用原声 sql
外键选择
生产环境可不添加外键(避免级联删除 / 更新的风险),改为应用层控制关联关系; 若需外键,可添加:ALTER TABLE sys_user_role ADD FOREIGN KEY (user_id) REFERENCES sys_user(id);。
